const mongodbUtil = require('mongoose');
const moment = require("moment/moment");
require('dotenv').config({path: './config/.env'});

// MongoDB 连接字符串
const host = process.env.HOST; // 替换为你的 MongoDB 主机
const port = process.env.PORT; // 替换为你的 MongoDB 端口
const database = process.env.DATABASE; // 替换为你的数据库名称
const username = process.env.MONGODB_USER; // 替换为你的数据库用户名
const password = process.env.PASSWORD; // 替换为你的数据库密码

// 检查环境变量是否设置, 确保环境变量都设置了
if (!host || !port || !database || !username || !password) {
    console.log(host, port, database, username, password);
    console.error('请检查是否设置了上述环境变量');
    process.exit(1);
}

// 构建连接字符串
const url = `mongodb://${username}:${password}@${host}:${port}/${database}`;

// 开启调试模式
mongodbUtil.set('debug', true);

const note = new mongodbUtil.Schema({
    mainContent: String,
    clueContent: String,
    summaryContent: String,
    userPhone: String,
    id: String,
    createTime: Date,
    updateTime: Date
});

const Note = mongodbUtil.model('Note', note);


async function insert(note) {
    const insertProcessor = new InsertProcessor();
    await insertProcessor.operateDocument(note);
}

async function getAllNotes() {
    const queryProcessor = new QueryProcessor();
    return await queryProcessor.operateDocument(Note);
}

async function pageQueryNotes(condition) {
    const pageQueryProcessor = new PageQueryProcessor();
    return await pageQueryProcessor.operateDocument(condition);
}

async function deleteNote(noteId) {
    const deleteProcessor = new DeleteProcessor();
    await deleteProcessor.operateDocument(noteId);
}

async function updateNote(doc) {
    const updateProcessor = new UpdateProcessor();
    await updateProcessor.operateDocument(doc);
}

class MongodbTemplate {

    async operateDocument(doc) {
        try { // 连接到 MongoDB 数据库
            console.log(`Connecting to MongoDB：${url}`);
            await mongodbUtil.connect(url);
            console.log('Connected to MongoDB successfully!');
            return await this.operate(doc);
        } catch (e) {
            console.error('Error:', e);
        } finally {
            // 关闭数据库连接
            await mongodbUtil.connection.close();
            console.log('MongoDB connection closed.');
        }
    }

    async operate(doc) {
        throw new Error('发生了异常');
    }
}

class InsertProcessor extends MongodbTemplate {
    async operate(doc) {
        const note = new Note(doc);
        await note.save();
        console.log('Document inserted successfully!');
    }
}

class QueryProcessor extends MongodbTemplate {
    async operate(doc) {
        const notes = await doc.find({}).lean(); // 使用 lean() 方法获取普通对象
        console.log("从MongoDB中查询到的笔记为：" + JSON.stringify(notes));
        return notes;
    }
}

// 获取上海时间
function getShangHaiDate(dateStr) {
    return moment(new Date(dateStr)).subtract(8, 'hours').toDate();
}

class PageQueryProcessor extends MongodbTemplate {
    async operate(condition) {
        const {page, limit} = condition;
        const skip = (page - 1) * limit;
        let query = {};
        // 根据用户的输入动态拼接查询条件
        // 时间范围查询
        const timeRangeQuery = {};
        if (condition.createTimeStart) {
            // 复制createTime的值，在这个的基础上进行修改
            timeRangeQuery.createTime = {...timeRangeQuery.createTime, $gte: getShangHaiDate(condition.createTimeStart)}
        }
        if (condition.createTimeEnd) {
            timeRangeQuery.createTime = {...timeRangeQuery.createTime, $lte: getShangHaiDate(condition.createTimeEnd)}
        }
        if (condition.updateTimeStart) {
            timeRangeQuery.updateTime = {...timeRangeQuery.updateTime, $gte: getShangHaiDate(condition.updateTimeStart)}
        }
        if (condition.updateTimeEnd) {
            timeRangeQuery.updateTime = {...timeRangeQuery.updateTime, $lte: getShangHaiDate(condition.updateTimeEnd)}
        }
        const keyword = condition.keyword;
        let keywordQuery = {};
        if (condition.keyword) {
            // 构建正则表达式
            const regex = new RegExp(keyword, 'i'); // 'i' 表示不区分大小写
            // 构建查询条件
            keywordQuery = {
                $or: [
                    {mainContent: regex},
                    {clueContent: regex},
                    {summaryContent: regex}
                ]
            };
        }
        if (Object.keys(timeRangeQuery).length > 0) {
            query = {...query, ...timeRangeQuery};
        }
        if (Object.keys(keywordQuery).length > 0) {
            query.$and = [keywordQuery, timeRangeQuery];
        }
        const notes = await Note.find(query)
            .sort({updateTime: -1})
            .skip(skip)
            .limit(limit)
            .lean(); // 使用 lean() 方法获取普通对象
        console.log("从MongoDB中查询到的笔记为：" + JSON.stringify(notes));
        return notes;
    }
}

class DeleteProcessor extends MongodbTemplate {
    async operate(noteId) {
        const result = await Note.findByIdAndDelete(noteId);
        console.log("从MongoDB中删除的笔记为：" + JSON.stringify(result));
    }
}

class UpdateProcessor extends MongodbTemplate {
    async operate(newNote) {
        const noteId = newNote.id;
        delete newNote.id;
        console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ": 从MongoDB中更新笔记，id：" + noteId);
        const result = await Note.findByIdAndUpdate(noteId, newNote, {new: true});
        console.log("从MongoDB中更新后的笔记为：" + JSON.stringify(result));
    }
}

module.exports = {
    insert,
    getAllNotes,
    pageQueryNotes,
    deleteNote,
    updateNote
}
